function createCharElement(char, isCurrent) {
    const charElement = createElem({
        tag: 'div',
        classes: ['char'],
        text: char
    });
    if (isCurrent) {
        charElement.classList.add('current');
    }
    return charElement;
}

function createButtonElement(text, eventHandler) {
    return createElem({
        tag: 'div',
        classes: ['button'],
        text: text,
        events: { click: eventHandler }
    });
}

function updateUI(id, data) {
    if (!data) return;

    const entry = document.querySelector(`.entry[data-id="${id}"]`);
    if (!entry) return;

    const stateElement = entry.querySelector('.state');
    stateElement.textContent = data.state;

    const cyclesElement = entry.querySelector('.cycles');
    cyclesElement.textContent = `${data.cycles}`;

    const tapeContainer = entry.querySelector('.tape');
    tapeContainer.setAttribute('data-head-position', data.head_position); // 添加或更新 data-head-position 属性

    const totalLength = data.tape.length;
    const start = Math.max(0, data.head_position - 50);
    const end = Math.min(totalLength, data.head_position + 50);

    let headElement = null;

    // Update or reuse existing elements
    for (let i = start, childIndex = 0; i < end; i++, childIndex++) {
        const char = data.tape[i];
        const isCurrent = i === data.head_position;

        if (childIndex < tapeContainer.children.length) {
            // Reuse existing element
            const charElement = tapeContainer.children[childIndex];
            if (charElement.textContent !== char) {
                charElement.textContent = char;
            }
            if (isCurrent) {
                charElement.classList.add('current');
                headElement = charElement;
            } else {
                charElement.classList.remove('current');
            }
        } else {
            // Add new element
            const charElement = createCharElement(char, isCurrent);
            tapeContainer.appendChild(charElement);
            if (isCurrent) {
                headElement = charElement;
            }
        }
    }

    // Remove extra elements
    while (tapeContainer.children.length > end - start) {
        tapeContainer.removeChild(tapeContainer.lastChild);
    }

    // Scroll to the head position
    if (headElement) {
        const offsetLeft = headElement.offsetLeft;
        const tapeWidth = tapeContainer.clientWidth;
        const charWidth = headElement.offsetWidth;
        tapeContainer.scrollLeft = offsetLeft - (tapeWidth / 2) + (charWidth / 2);
    }

    // Update blank symbol
    const blankSymbolElement = entry.querySelector('.blank-symbol');
    blankSymbolElement.textContent = `${data.blank_symbol}`;
}

function createNewMachineUI(machineId, initialTape, initialState, headPosition, cycles = 0, blankSymbol = ' ') {
    const entry = createElem({
        tag: 'div',
        classes: ['entry'],
        attributes: { 
            'data-id': machineId,
        }
    });

    const sequenceNumber = createElem({
        tag: 'div',
        classes: ['sequence-number'],
        text: machineId
    });

    const machineContainer = createElem({
        tag: 'div',
        classes: ['machine-container']
    });

    const stateDisplay = createElem({
        tag: 'div',
        classes: ['state'],
        text: initialState
    });

    const cyclesDisplay = createElem({  // New element for displaying cycles
        tag: 'div',
        classes: ['cycles'],
        text: `${cycles}`
    });

    const blankSymbolDisplay = createElem({  // New element for displaying blank symbol
        tag: 'div',
        classes: ['blank-symbol'],
        text: `${blankSymbol}`
    });

    const tapeDisplay = createElem({
        tag: 'div',
        classes: ['tape'],
        attributes: { 'data-head-position': headPosition } // 初始化 data-head-position 属性
    });

    initialTape.split("").forEach((char, index) => {
        tapeDisplay.appendChild(createCharElement(char, index === headPosition));
    });

    const editButton = createButtonElement('编辑', edit);
    const deleteButton = createButtonElement('删除', del);
    const addButton = createButtonElement('新增机器', add);
    const copyButton = createButtonElement('复制', copy); // New button for copying

    machineContainer.appendChild(stateDisplay);
    machineContainer.appendChild(cyclesDisplay);  // Append cycles display to container
    machineContainer.appendChild(blankSymbolDisplay);  // Append blank symbol display
    machineContainer.appendChild(tapeDisplay);
    machineContainer.appendChild(editButton);
    machineContainer.appendChild(deleteButton);
    machineContainer.appendChild(copyButton); // Append the copy button

    entry.appendChild(sequenceNumber);
    entry.appendChild(machineContainer);

    document.querySelector('.main-content').appendChild(entry);
}

function openModal() {
    document.getElementById("myModal").style.display = "block";
}

function closeModal() {
    document.getElementById("myModal").style.display = "none";
}

function confirmAction() {
    if (document.querySelector('input[name="act"]').value === "add") {
        createMachine(); // Call createMachine on confirmation
    } else {
        const id = document.querySelector('input[name="id"]').value;
        updateMachine(id);
    }
    closeModal();
}

function add() {
    // Clear any previous values
    document.getElementById("description").value = "";
    document.getElementById("initialTape").value = "";
    document.getElementById("initialState").value = "";

    // Set hidden fields if necessary
    document.querySelector('input[name="act"]').value = "add"; // Indicate action
    document.querySelector('input[name="id"]').value = ""; // No specific ID for new machine

    // Open the modal
    openModal();
}

async function edit(event) {
    const entry = event.target.closest('.entry');
    const id = entry.querySelector('.sequence-number').textContent.trim();

    // 显示 body 下的 loading 图层
    const loadingOverlay = document.getElementById("loadingOverlay");
    loadingOverlay.style.display = "flex";

    try {
        const response = await fetch(`/machine/${id}`);
        if (!response.ok) throw new Error("Failed to fetch machine data");

        const machineData = await response.json();

        // 填充模态框数据
        document.getElementById("description").value = machineData.raw_instructions || "";
        document.getElementById("initialTape").value = machineData.tape || "";
        document.getElementById("initialState").value = machineData.state || "";
        document.getElementById("blankSymbol").value = machineData.blank_symbol || " ";

        // 设置 hidden 字段
        document.querySelector('input[name="act"]').value = "edit";
        document.querySelector('input[name="id"]').value = id;

        // 隐藏 loading 图层
        loadingOverlay.style.display = "none";

        // 显示模态框
        openModal();
    } catch (error) {
        console.error(error);
        alert("加载数据失败，请重试！");
        loadingOverlay.style.display = "none";
    }
}



async function del(event) {
    if (!confirm('确定要删除此机器吗？')) return;

    const entry = event.target.closest('.entry');
    const id = entry.querySelector('.sequence-number').textContent.trim();

    entry.remove();  // 从 DOM 中移除

    const response = await fetch(`/delete_machine/${id}`, { method: "POST" });
    const data = await response.json();
}

async function copy(event) {
    const entry = event.target.closest('.entry'); // Get the closest .entry element

    const id = entry.querySelector('.sequence-number').textContent.trim(); // Get machine ID

    // Call the API to copy the machine
    const response = await fetch(`/copy_machine/${id}`, { method: "POST" });

    if (!response.ok) {
        alert("Failed to copy the machine. Please try again.");
        return;
    }

    const newMachine = await response.json(); // Get the new machine data

    // Now update the UI with the new machine
    createNewMachineUI(
        newMachine.id, 
        newMachine.tape, 
        newMachine.state, 
        newMachine.head_position, 
        newMachine.cycles, 
        newMachine.blank_symbol
    );
}
